
public class Controller  {
	// coordenadas del agente
	private Agente robot;
	private int x;
	private int y;
	
	private int maxX;
	private int maxY;
	
	private int total_moves;
	private boolean demoMode;
	private double [][] heuristicaEspacioLibre;
	
	private boolean [][] observado;
	
	final public static int INFINITO=Integer.MAX_VALUE;

	// coordenas del goal
	private int goal_x;
	private int goal_y;
	
	private boolean terminar;

	private double time_limit;
	// el mapa
	private char[][] map;

	// la vista
	private GUI ventana;

	public Controller(String clase_alumno, char[][] map, int x, int y, int gx,
			int gy,int maxX, int maxY, boolean demoMode, double time_limit) {
		this.map = map;
		this.x = x;
		this.y = y;
		this.goal_x = gx;
		this.goal_y = gy;
		this.maxX = maxX;
		this.maxY = maxY;
		this.total_moves = 0;
		this.demoMode = demoMode;
		this.terminar=false;
		this.time_limit=time_limit;

		observado=new boolean[maxX][maxY];
		heuristicaEspacioLibre = new double[maxX][maxY];
		for (int i=0;i<maxX;i++) {
			for (int j=0; j<maxY;j++) {
				heuristicaEspacioLibre[i][j]=Heuristica(i, j);
				observado[i][j]=false;
			}
		}

		if (demoMode) {
			this.ventana = new GUI(map, x, y, gx, gy,observado);
		}

		// Obtenemos la clase del alumno mediante Java Reflection;
		// robot = new GreedySearcher();
//		try {
//			Class clase = Class.forName(clase_alumno);
//			Class clase = Class.forName("DFSSearcher");
//			robot = (Agente) clase.newInstance();
			robot = new DFSSearcher();
			robot.Inicializar(Observar(),map);
//		} catch (Exception e) {
//			System.out.println("Error creando la clase "+clase_alumno);
//			System.exit(0);

//		}
	}

	public int getMaxX() {
		return maxX;
	}
	
	public int getMaxY() {
		return maxY;
	}
	private Observacion Observar() {
		// Retornamos la observación correspondiente
		Observacion obs = new Observacion(x,y,goal_x,goal_y);
		return obs;
	}

	private Boolean Disponible(int i, int j) {
		return (map[i][j] == 'g' || map[i][j] == 'G' || map[i][j] == '.');

	}

	private Double Heuristica(int i, int j) {
		return (double) (Math.abs(i - goal_x) + Math.abs(j - goal_y));

	}


	public long getCpuTime() {
		return System.nanoTime();
	}
	
	public boolean Seguir() {
		return !terminar && Heuristica(x, y) != 0.0;
	}

	private long t_computo=0;
	
	// Metodos de ActionListener
	//@Override
	public void run() {
//		long id = java.lang.Thread.currentThread( ).getId();
		long t_antes,t_despues;
	

		if (Seguir()) {
			Observacion nueva_observacion = Observar();
						
			t_antes=getCpuTime();
			
			Direccion next = robot.Mover(nueva_observacion,t_computo-t_antes);

			t_despues=getCpuTime();
			
			t_computo += t_despues-t_antes;
						
			if (t_computo/10E9>time_limit) {
				System.out.println("Tiempo excedido. Tomo t="+t_computo+ time_limit);
				terminar=true;
				total_moves=-2;
			}
			
			int newx = x + next.X();
			int newy = y + next.Y();

			if (Disponible(newx, newy)) {
				x = newx;
				y = newy;
			}
		

			if (demoMode) ventana.Actualizar(x, y, total_moves);
			total_moves++;
			if (!Seguir()) {
				System.out.println("costo solución=" + total_moves);
				System.out.println("tiempo total=" + t_computo/10E9 + " seg.");
			}
		}

	}

}
